#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/3/27 0:00
# @Author  : Grayson Liu
# @Email   : graysonliu@foxmail.com
# @File    : ViewGraphicsForm.py

from PyQt5.Qt import *
import threading

from ui.Ui_ViewGraphicsForm import Ui_ViewGraphicsForm

from CustomFigureCanvas import CustomFigureCanvas

from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar

from CustomSignal import CustomSignal

from GeoGraphicProcess import GeoGraphicProcess

import numpy as np


class ViewGraphicsForm(QWidget, Ui_ViewGraphicsForm):
    global_signal = CustomSignal()

    def __init__(self, parent=None):
        """
        初始化
        :param parent: 父窗体
        """
        super(ViewGraphicsForm, self).__init__(parent)
        self.setupUi(self)

        # 成员变量
        self.current_raster = 1
        self.current_geo_graphic = None

        # 添加CustomFigureCanvas到窗体中
        layout = QVBoxLayout(self.graphicView)
        self.customFig = CustomFigureCanvas(self.graphicView)
        self.figToolbar = NavigationToolbar(self.customFig, self)  # 添加一个NavigationToolbar在FigureCanvas下方
        layout.addWidget(self.customFig)
        layout.addWidget(self.figToolbar)

        # 初始化tableGraphicAttr
        self.tableGraphicAttr.setColumnCount(2)
        self.tableGraphicAttr.setHorizontalHeaderLabels(["属性", "值"])
        self.tableGraphicAttr.horizontalHeader().setFont(QFont("宋体", 8, QFont.Black))
        self.tableGraphicAttr.setColumnWidth(0, 80)
        self.tableGraphicAttr.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.tableGraphicAttr.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.tableGraphicAttr.setSelectionBehavior(QAbstractItemView.SelectRows)

        # 按钮关联槽函数
        self.btnOpenGraphic.clicked.connect(self.show_graphic_task)
        self.btnSaveGraphic.clicked.connect(self.save_graphic_task)

        # 自定义信号，关联槽函数
        ViewGraphicsForm.global_signal.draw_picture.connect(self.show_picture)
        ViewGraphicsForm.global_signal.update_text.connect(self.show_message)
        ViewGraphicsForm.global_signal.append_item.connect(self.add_list_item)
        ViewGraphicsForm.global_signal.clear_all_item.connect(self.clear_list_item)

    def show_picture(self, canvas: CustomFigureCanvas, array: np.ndarray):
        """
        自定义信号draw_picture的槽函数，属于Ui线程，根据传入图片矩阵信息更新控件
        :param canvas: 控件对象
        :param array: 图片矩阵
        :return:
        """
        canvas.show_picture(array)

    def show_message(self, message: str):
        """
        自定义信号update_text的槽函数，属于Ui线程，根据传入字符串信息，添加到末尾
        :param message: 字符串信息
        :return:
        """
        self.textConsole.append(message)
        self.textConsole.ensureCursorVisible()  # 保持光标一直可见，即保持在最后一行

    def add_list_item(self, tableWidget: QTableWidget, attr: str, value: str):
        """
        自定义信号append_item的槽函数，属于Ui线程，根据传入的信息，在指定表格控件添加一行
        :param tableWidget: 表格控件对象
        :param attr: 属性字符串
        :param value: 值字符串
        :return:
        """
        item_attr = QTableWidgetItem(attr)
        item_attr.setFont(QFont("宋体", 8))
        item_value = QTableWidgetItem(value)
        item_attr.setFont(QFont("宋体", 8))
        row = tableWidget.rowCount()
        tableWidget.insertRow(row)
        tableWidget.setItem(row, 0, item_attr)
        tableWidget.setItem(row, 1, item_value)
        tableWidget.resizeRowsToContents()

    def clear_list_item(self, tableWidget: QTableWidget):
        """
        自定义信号clear_all_item的槽函数，属于Ui线程，收到信号后清空表格控件的所有项目
        :param tableWidget: 表格控件对象
        :return:
        """
        tableWidget.clearContents()
        tableWidget.setRowCount(0)

    def set_current_graphic(self, geo_graphic: GeoGraphicProcess):
        """
        自定义信号update_graphic的槽函数，属于Ui线程，收到信号后，更新成员变量current_graphic的图像矩阵
        :param geo_graphic: 遥感影像对象
        :return:
        """
        self.current_geo_graphic = geo_graphic

    def show_graphic_task(self):
        """
        点击“打开图像”按钮信号的槽函数
        :return:
        """

        def threadFunc(path: str, raster_num: int):
            """
            线程体，负责打开图片，给Ui线程发信号更新界面
            :param raster_num: 波段序号
            :param path: 有效的图片文件路径
            :return:
            """
            # 给Ui线程发信号
            ViewGraphicsForm.global_signal.update_text.emit("正在读取文件：{}".format(path))
            # 获得遥感图像的基本信息和地理信息，显示到表格控件中
            geo_graphic = GeoGraphicProcess()
            geo_graphic.read_file(path)
            geo_graphic_info = geo_graphic.get_geo_info()
            ViewGraphicsForm.global_signal.clear_all_item.emit(self.tableGraphicAttr)  # 先清空内容
            for key, value in geo_graphic_info.items():
                ViewGraphicsForm.global_signal.append_item.emit(self.tableGraphicAttr, key, value)
            # 读取遥感影像信息，可能会比较耗时
            im_gray = geo_graphic.get_graphic(raster_num)
            ViewGraphicsForm.global_signal.draw_picture.emit(self.customFig, im_gray)
            # 读取的遥感影像进行保存
            self.current_geo_graphic = geo_graphic
            # 完成后，给Ui线程发信号
            ViewGraphicsForm.global_signal.update_text.emit("已完成文件读取：{}".format(path))

        # 打开文件浏览器
        pic_path, pic_type = QFileDialog.getOpenFileName(self, "选择图片文件", filter="GeoTiff Files(*.tif)")
        if pic_path == "":
            return

        # 弹出一个对话框，让用户选择是哪一个波段
        num, flag = QInputDialog.getInt(self, "输入波段数", "请输入波段序号（1到8的整数）", 1, 1, 8, 1)
        if flag:
            ViewGraphicsForm.global_signal.update_text.emit("选择波段数：{}".format(num))
            self.current_raster = num
        else:
            ViewGraphicsForm.global_signal.update_text.emit("未选择波段")

        # 启动一个线程去完成打开读取图片的操作
        thread = threading.Thread(target=threadFunc, args=(pic_path, num))
        thread.start()

    def save_graphic_task(self):
        """
        点击“保存图像”按钮的槽函数
        :return:
        """
        # 打开文件浏览器
        pic_path, pic_type = QFileDialog.getSaveFileName(self, "选择保存位置", filter="JPEG Files(*.jpg)")
        if pic_path == "":
            return
        self.current_geo_graphic.save_graphic(pic_path, 50, self.current_raster)
        ViewGraphicsForm.global_signal.update_text.emit("已保存文件：{}".format(pic_path))
